package com.net.xpay.admin.secutiry;

import com.net.xpay.core.constant.AdminWebConstant;
import com.net.xpay.core.helper.DomainHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.session.web.http.CookieSerializer;

import java.util.ArrayList;
import java.util.List;

/**
  on 27/01/2018.
 */
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
    @Autowired
    private AuthenticationSuccessHandler loginSuccessHandler;
    @Autowired
    private AuthenticationFailureHandler loginFailureHandler;
    @Autowired
    private AccessDecisionManager accessDecisionManager;
    @Autowired
    private AuthenticationEntryPoint restAuthenticationEntryPoint;
    @Autowired
    private LogoutSuccessHandler successLogoutHandler;
    @Autowired
    private SessionManager sessionManager;
    @Autowired
    private DomainHelper domainHelper;
    @Autowired
    private SecurityHelper securityHelper;

    @Bean
    public AuthenticationManager authenticationManagerBeanExport() throws Exception {
        return super.authenticationManagerBean(); //WebSecurityConfigurerAdapter中没有暴漏出来
    }

    @Bean
    public FormLoginFilter formLoginFilter() throws Exception {
        FormLoginFilter filter = new FormLoginFilter();
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationSuccessHandler(loginSuccessHandler);
        filter.setAuthenticationFailureHandler(loginFailureHandler);
        return filter;
    }

    @Bean
    public RememberMeFilter rememberMeFilter() throws Exception {
        RememberMeFilter rememberMeFilter = new RememberMeFilter();
        rememberMeFilter.setSessionManager(sessionManager);
        rememberMeFilter.setAuthenticationManager(authenticationManagerBeanExport());
        rememberMeFilter.setSecurityHelper(securityHelper);
        rememberMeFilter.setDomainHelper(domainHelper);

        return rememberMeFilter;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        for (AuthenticationProvider authenticationProvider : authenticationProviders) {
            auth.authenticationProvider(authenticationProvider);
        }
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().filterSecurityInterceptorOncePerRequest(true);
        http.authorizeRequests()
                .antMatchers("/admin/**", "/base/**").authenticated().accessDecisionManager(accessDecisionManager)
                .antMatchers("/common/**").permitAll()
                .antMatchers("/open/**").permitAll()
                .and().anonymous();
        http.sessionManagement().invalidSessionUrl(null);

        http.addFilterBefore(formLoginFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(rememberMeFilter(), AnonymousAuthenticationFilter.class); //处理remember me的功能
        http.csrf().disable();
        http.logout().logoutRequestMatcher(new AntPathRequestMatcher(AdminWebConstant.LOGOUT_URL))
                .addLogoutHandler(new SecurityContextLogoutHandler()).logoutSuccessHandler(successLogoutHandler);

        http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
    }

    @Bean
    public CookieSerializer cookieSerializer() {
        CustomDomainNameCookieSerializer serializer = new CustomDomainNameCookieSerializer();

        serializer.setDomainName(null); //不需设置指定的值
        serializer.setDomainNamePattern(null);
        serializer.setJvmRoute(null);
        serializer.setUseBase64Encoding(true);
        serializer.setRememberMeRequestAttribute(null);
        serializer.setUseHttpOnlyCookie(false);
        serializer.setUseSecureCookie(false);

        serializer.setDomainHelper(domainHelper);
        serializer.setCookieName(AdminWebConstant.SESSION_COOKIE_NAME);
        serializer.setCookiePath("/");
        serializer.setCookieMaxAge(AdminWebConstant.SESSION_COOKIE_MAX_AGE);
        return serializer;
    }
}
